package org.zsk.cs.algorithnm.loadbalance;

import org.zsk.cs.algorithnm.loadbalance.sendorder.LoadBalance;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zsk
 * 2021/3/11 下午3:56
 */
public class RoundLoaderBalancer implements LoadBalance<Service> {

    private static AtomicInteger idx = new AtomicInteger(0);
    @Override
    public Service pickOne() {
        List<Service> serviceList = getServiceList();
        int index = getNextNonNegative();
        for (int i = 0; i < serviceList.size(); i++) {
            //获取服务
            Service service = serviceList.get((i + index) % serviceList.size());
            //判断服务是否可用
            if (service.isAvailable()) {
                return service;
            }
        }
        return null;
    }

    /**
     * 假设有这么一个获取全部服务的列表
     *
     * @return
     */
    public List<Service> getServiceList() {
        List<Service> serviceList = new ArrayList<>();
        Service service0 = new Service("service0");
        Service service1 = new Service("service1");
        Service service2 = new Service("service2");
        Service service3 = new Service("service3");
        Service service4 = new Service("service4");
        Service service5 = new Service("service5");
        serviceList.add(service0);
        serviceList.add(service1);
        serviceList.add(service2);
        serviceList.add(service3);
        serviceList.add(service4);
        return serviceList;
    }

    private int getNextNonNegative() {
        return getNonNegative(idx.incrementAndGet());
    }

    /**
     * 通过二进制位操作将originValue转化为非负数:
     * 0和正数返回本身
     * 负数通过二进制首位取反转化为正数或0（Integer.MIN_VALUE将转换为0）
     * return non-negative int value of originValue
     *
     * @param originValue
     * @return positive int
     */
    public int getNonNegative(int originValue) {
        return 0x7fffffff & originValue;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            System.out.println(new RoundLoaderBalancer().pickOne().toString());
        }
    }
}

